//
//  WYFJsBridge.m
//  NetEaseFinancial
//
//  Created by 吴玉峰 on 8/18/15.
//  Copyright (c) 2015 吴玉峰. All rights reserved.
//

#import "WYFJSBridge.h"

#import "WYFJSCommand.h"
#import "WYFWebInterface.h"
#import "WYFWebViewProxyDelegate.h"

#import <UIKit/UIKit.h>

static long seed = 0;

/**
 * js方法的命名空间, js里的使用 window.__JavascriptBridge__.xxx 调用objective-c提供给js的接口
 */
static NSString *const API_NAMESPACE = @"__JavascriptBridge__";

static NSString *const VALUE_SERIAL_PREFIX = @"native_";
static NSString *const VALUE_JAVASCRIPT_FUNCTION_NAME = @"jsb.__native_callback";

@interface WYFJSBridge ()

@property (nonatomic, weak) WYFWebViewProxyDelegate *webViewProxyDelegate;
@property (nonatomic, strong) NSMutableDictionary *objectiveCFunctionMap;
@property (nonatomic, strong) NSMutableDictionary *javascriptCallBackMap;

@end

@implementation WYFJSBridge

- (instancetype)initWithWebViewProxyDelegate:(WYFWebViewProxyDelegate *)webViewProxyDelegate {
    if ((self = [super init])) {

        self.webViewProxyDelegate = webViewProxyDelegate;
        [self configureDependencies];
    }
    return self;
}

- (void)configureDependencies {
    self.objectiveCFunctionMap = [NSMutableDictionary dictionaryWithCapacity:5];
    self.javascriptCallBackMap = [NSMutableDictionary dictionaryWithCapacity:1];
    WYFWebInterface *interface = [[WYFWebInterface alloc] initWithJsBridge:self];
    [self.webViewProxyDelegate addJavascriptInterface:interface WithName:API_NAMESPACE];
}

- (BOOL)handleCommand:(WYFJSCommand *)cmd {
    int type = [cmd.type intValue];
    NSLog(@"HANDLE_COMMAND.TYPE = %d", type);
        switch (type) {
    case EXECUTE_NATIVE_FUNCTION:
        [self executeObjectiveCFunction:cmd];
        return YES;

    case EXECUTE_JAVASCRIPT_CALLBACK:
        [self executeJavascriptCallback:cmd];
        return YES;

    case EXECUTE_NATIVE_CALLBACK:
    case EXECUTE_JAVASCRIPT_FUNCTION:
        [self executeJavascriptFunction:cmd];
        return YES;
        break;

    default:
        break;
    }

    return NO;
}

+ (NSString *)createSerial {
    return [NSString stringWithFormat:@"%@%ld", VALUE_SERIAL_PREFIX, ++seed];
}

- (void)registerCommandWithName:(NSString *const)name objectiveCFunction:(id)objectiveCFunction {
    NSLog(@"=======%@=======%@=======",name,objectiveCFunction);
    self.objectiveCFunctionMap[name] = objectiveCFunction;
}

/**
 * 提供给 native 调用 webview 中的 javascript 方法, javascript 的主要接口函数
 *
 * @param cmdName
 * @param params
 * @param callback
 */
- (void)execute:(NSString *)cmdName params:(NSDictionary *)params jsCallback:(id)jsCallback {
    WYFJSCommand *command = [[WYFJSCommand alloc] initCommandWithName:cmdName params:params type:[NSNumber numberWithInt:EXECUTE_JAVASCRIPT_FUNCTION]];
    NSLog(@"%@", command.description);
    if (jsCallback != nil) {
        self.javascriptCallBackMap[command.serial] = jsCallback;
    }
    [self handleCommand:command];
}

/**
 * 执行command对应的native方法(被js调用)
 *
 * @param command
 */
- (void)executeObjectiveCFunction:(WYFJSCommand *)cmd {
    NSLog(@"JSBridge.executeObjectiveCFunction.enter");
    ObjectiveCFunction onExecute = self.objectiveCFunctionMap[cmd.name];
    if (onExecute != nil) {
        onExecute(cmd);
    } else {
        NSLog(@"JSBridge.executeObjectiveCFunction:command '%@' not found", cmd.name);
    }
    NSLog(@"JSBridge.executeObjectiveCFunction.leave");
}

/**
 * 执行java对js的调用的回调
 *
 * @param command
 */
- (void)executeJavascriptCallback:(WYFJSCommand *)cmd {
    JavascriptCallback onComplete = self.javascriptCallBackMap[cmd.serial];
    if (onComplete != nil) {
        onComplete(cmd);
    } else {
        NSLog(@"JSBridge.executeJavascriptCallback:command '%@' not found", cmd.name);
    }
}

/**
 * 执行command对应的javascript方法(被native调用)
 *
 * @param command
 * @throws JSONException
 */
- (void)executeJavascriptFunction:(WYFJSCommand *)cmd {
    NSString *js = [NSString stringWithFormat:@"%@(%@)", VALUE_JAVASCRIPT_FUNCTION_NAME, cmd.description];
    NSLog(@"excuteJS:%@", js);
    [self.webViewProxyDelegate executeJavasciptFunction:js];
}

@end
